<?php

include_once("config.inc.php");

/**************************************************************
*  fonction permettant de se connecter à la base de données   *
***************************************************************/
function connexion($host,$user,$mdp,$db){

	$link = mysql_connect($host,$user,$mdp) or die ("pas de connexion");
	mysql_select_db($db,$link) or die ("pas de connexion");	
	return $link;
	
}

$link = connexion($host,$user,$mdp,$db);

//supprime les backslash dans les variables
function sanitizeVariables(&$item, $key) {
    if (!is_array($item)) {
        // undoing 'magic_quotes_gpc = On' directive 
        if (get_magic_quotes_gpc())
            $item = stripcslashes($item);
    } 
} 

//retourne la structure des individus (nombre de gènes, taille, ...)
function demanderStructureIndividu($idProbleme){

	$req="SELECT * FROM codage c, gene g, probleme p WHERE p.id_probleme = '$idProbleme' AND p.id_codage = c.id_codage AND g.id_probleme = '$idProbleme'";

	$resMess = mysql_query($req);
	$retour = array();
	$retour['liste_gene'] = array();
	$compt = 0;
	while($codage = mysql_fetch_array($resMess)) {
		$retour['nom_codage'] = $codage['nom_codage'];
		$retour['liste_gene'][$compt]['id_gene'] = $codage['id_gene'];
		$retour['liste_gene'][$compt]['valeur_min'] = $codage['valeur_min'];
		$retour['liste_gene'][$compt]['valeur_max'] = $codage['valeur_max'];
		$retour['liste_gene'][$compt]['finesse'] = $codage['finesse'];
		$retour['liste_gene'][$compt]['taille'] = $codage['taille'];
		$retour['liste_gene'][$compt]['position'] = $codage['position'];
		$compt++;
	}

	return json_encode($retour);

}

//ajoute un individu à la BdD (contenu dans le JSON)
function creerIndividu($listeGene){

	$reussi = true;
	if(!$liste = json_decode($listeGene, 1))
		$reussi = false;

	$req = "INSERT INTO individu values(null, 1, CURRENT_TIMESTAMP)";

	if(mysql_query($req)){

		$idIndiv = mysql_insert_id();
		$req = "INSERT INTO evaluation values('".idCritereDefaut."', '$idIndiv', 0.0)";
		if(mysql_query($req)){
			$i = 0;
			while($reussi and $i < count($liste['liste'])) {

				$req2 = "INSERT INTO allele values('$idIndiv', '".$liste['liste'][$i]['id']."', '".$liste['liste'][$i]['valeurR']."', '".$liste['liste'][$i]['valeurB']."')";
				if(!mysql_query($req2))
					$reussi = false;
				$i++;
			}
		}
		else
			$reussi = false;
	}
	else
		$reussi = false;
	
	return $reussi;

}

//Retourne un individu aléatoire évalué ou non (suivant le 2ème paramètre) sous le format JSON
function obtenirIndiv($idProbleme, $nonEvalue) {
		
	$indivChoisi = 0;
	
	$evaluation = "";
	if($nonEvalue)
		$evaluation = " AND i.id_etat = '1'";
	else
		$evaluation = " AND (i.id_etat = '1' OR i.id_etat = '2')";

	$req="SELECT DISTINCT i.id_individu AS id_individu FROM allele a, gene g, individu i 
		WHERE i.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme'$evaluation ORDER BY RAND()";

	$resIndiv = mysql_query($req);
	$indiv = mysql_fetch_array($resIndiv);
	if(isset($indiv[0]))
		$indivChoisi = $indiv[0];
	
	return afficherIndivJSON($indivChoisi);

}

//Retourne dans le format JSON un individu (suivant le 1er paramètre)
function afficherIndivJSON($indivChoisi) {

	$retour = array();
	$retour['id_indiv'] = $indivChoisi;
	$retour['liste_gene'] = array();
	
	$req="SELECT * FROM allele WHERE id_individu = '$indivChoisi'";
	$resAllele = mysql_query($req);
	$compt = 0;
	while($allele = mysql_fetch_array($resAllele)) {
		$retour['liste_gene'][$compt]['id_gene'] = $allele['id_gene'];
		$retour['liste_gene'][$compt]['alleleR'] = $allele['alleleR'];
		$retour['liste_gene'][$compt]['alleleB'] = $allele['alleleB'];
		$compt++;
	}
	
	$req="SELECT * FROM evaluation WHERE id_individu = '$indivChoisi'";
	$resFitness = mysql_query($req);
	$fitness = mysql_fetch_array($resFitness);
	$retour['fitness'] = 0;
	if(isset($fitness['fitness']))
		$retour['fitness'] = $fitness['fitness'];
	
	return json_encode($retour);

}

//enregistre le fitness de l'individu choisi
function enregistrementFitness($idIndiv, $fitness) {

	$req = "UPDATE individu SET id_etat='2' WHERE id_individu='$idIndiv'";
	$req2 = "UPDATE evaluation SET fitness='$fitness' WHERE id_individu='$idIndiv'";
	
	if(mysql_query($req) and mysql_query($req2))
		return true;
	else
		return false;
	

}

//Retourne la formule d'évaluation suivant le problème
function obtenirFonctionEval($idProbleme) {
	
	$retour = array();
	
	$req = "SELECT c.formule FROM critere c, probleme p WHERE c.id_critere = p.id_critere AND p.id_probleme = '$idProbleme'";
	$res = mysql_query($req);
	$formule = mysql_fetch_array($res);
	$retour['formule'] = "";
	if(isset($formule[0]))
		$retour['formule'] = $formule[0];
	/*
	$req = "SELECT c.formule FROM critere c, evaluation e, allele a, gene g WHERE c.id_critere = e.id_critere AND e.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme'";
	$res = mysql_query($req);
	$formule = mysql_fetch_array($res);
	$retour['formule'] = "";
	if(isset($formule[0]))
		$retour['formule'] = $formule[0];
	*/
	return json_encode($retour);

}

//met à jour les caractéristiques d'un individu (utilisé par la mutation)
function updateIndiv($jsonIndiv) {

	$reussi = true;
	if(!$json = json_decode($jsonIndiv,1))
		$reussi = false;
	
	$req = "UPDATE individu SET id_etat='1' WHERE id_individu='".$json['idIndiv']."'";
	echo $req;
	if(mysql_query($req)) {
		for($i = 0; $i < count($json['listeGene']); $i++) {
			$req = "UPDATE allele SET alleleR='".$json['listeGene'][$i]['alleleR']."', alleleB='".$json['listeGene'][$i]['alleleB']."' WHERE id_individu='".$json['idIndiv']."' AND id_gene='".$json['listeGene'][$i]['idGene']."'";
			echo $req;
			if(!mysql_query($req))
				$reussi = false;
		}

	}
	else
		$reussi = false;
	
	
	return $reussi;
}

//Retourne 2 individus parents en utilisant la roue de la fortune
function selection($idProbleme, $nbParents) {
	
	$retour = array();
	$retour['liste_indiv'] = array();
	$listeParentDejaChoisi = array();
	
	$sommeFitness = 0;
	$tabIdIndiv = array();
	$tabFitness = array();
	$indexCourant = 0;

	$req = "SELECT DISTINCT(i.id_individu), e.fitness FROM evaluation e, allele a, gene g, individu i 
		WHERE i.id_individu = e.id_individu AND e.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme' AND id_etat = '2' ORDER BY e.fitness DESC";
	$resFit = mysql_query($req);
	while($fitness = mysql_fetch_array($resFit)) {
		//$sommeFitness += $fitness[1];
		//il ne faut pas que les 2 parents aient le même fitness car sinon leurs 2 fils seront identiques
		if(!in_array($fitness[1], $tabFitness)) {
			$tabIdIndiv[$indexCourant] = $fitness[0];
			$tabFitness[$indexCourant] = $fitness[1];
			$indexCourant++;
		}
	}
	
	$nbIndiv = $indexCourant;
	
	//si il existe assez de parents
	if(count($tabIdIndiv) >= $nbParents) {
		
		//tant qu'on a pas encore choisi assez de parents (ici 2)
		for($i = 0; $i < $nbParents; $i++) {
			
			//calcul la somme des fitness
			$sommeFitness = 0;
			for($j = 0; $j < count($tabFitness); $j++)
				if(!in_array($j, $listeParentDejaChoisi))
					$sommeFitness += $tabFitness[$j];
			
			$indexCourant = 0;
			$fitnessHasard = frand(0, $sommeFitness, 5);
			$sommeCourante = 0;
			//parcours la liste et s'arrete dès que le fitness choisi au hasard est 
			//supérieur à la somme de fitness de tous les indiv déjà parcourus
			//roulette
			while($sommeCourante < $fitnessHasard) {
				if(!in_array($indexCourant, $listeParentDejaChoisi))
					$sommeCourante += $tabFitness[$indexCourant];
				$indexCourant++;
			}
			
			if($indexCourant>0)
				$indexCourant--;
			
			//si on a déjà choisi cet individu, on choisi celui qui se trouve avant
			while(in_array($indexCourant, $listeParentDejaChoisi) and $indexCourant > 0)
				$indexCourant--;
			
			$indivChoisi = $tabIdIndiv[$indexCourant];
			
			//on sait que l'individu choisi ne pourra plus l'être
			$listeParentDejaChoisi[count($listeParentDejaChoisi)] = $indexCourant;
			
			$retour['liste_indiv'][$i]['id_indiv'] = $indivChoisi;
			$retour['liste_indiv'][$i]['liste_gene'] = array();

			$req="SELECT * FROM allele WHERE id_individu = '$indivChoisi'";
			$resAllele = mysql_query($req);
			$compt = 0;
			while($allele = mysql_fetch_array($resAllele)) {
				$retour['liste_indiv'][$i]['liste_gene'][$compt]['id_gene'] = $allele['id_gene'];
				$retour['liste_indiv'][$i]['liste_gene'][$compt]['alleleR'] = $allele['alleleR'];
				$retour['liste_indiv'][$i]['liste_gene'][$compt]['alleleB'] = $allele['alleleB'];
				$compt++;
			}
		}
		return json_encode($retour);
	
	}
	else
		echo '{"success": false, "message": "pas assez de parents"}';
	
}

//désactive un individu (utilisé par le client de prédation) en utilisant la roue de la fortune
//les individus le plus auront plus de chance d'être supprimé
function predation($idProbleme) {
	
	$reussi = false;
	
	$sommeFitness = 0;
	$tabIdIndiv = array();
	$tabFitness = array();
	$indexCourant = 0;

	$req = "SELECT MAX(e.fitness) FROM evaluation e, allele a, gene g, individu i 
		WHERE i.id_individu = e.id_individu AND e.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme' AND id_etat = '2'";
	$resMax = mysql_query($req);
	$max = mysql_fetch_array($resMax);
	$maximum = 1;
	if(isset($max[0]) and floatval($max[0]) > $maximum)
		$maximum = floatval($max[0]);
	
	$req = "SELECT DISTINCT(i.id_individu), e.fitness FROM evaluation e, allele a, gene g, individu i 
		WHERE i.id_individu = e.id_individu AND e.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme' AND id_etat = '2' ORDER BY e.fitness ASC";
	$resFit = mysql_query($req);
	while($fitness = mysql_fetch_array($resFit)) {
		$sommeFitness += ($maximum - $fitness[1]);
		$tabIdIndiv[$indexCourant] = $fitness[0];
		//ceux qui ont le plus mauvais fitness seront choisi car ils auront dans notre roulette le meilleur fitness
		$tabFitness[$indexCourant] = ($maximum - $fitness[1]);
		$indexCourant++;
	}
	
	//si on a au moins 1 individu a tuer
	if($indexCourant > 0) {
		$indexCourant = 0;
		$fitnessHasard = frand(0, $sommeFitness, 5);
		$sommeCourante = 0;
		//parcours la liste et s'arrete dès que le fitness choisi au hasard est 
		//supérieur à la somme de fitness de tous les indiv déjà parcourus
		//roulette
		while($sommeCourante < $fitnessHasard) {
			$sommeCourante += $tabFitness[$indexCourant];
			$indexCourant++;
		}
		
		if($indexCourant>0)
			$indexCourant--;
		
		$indivChoisi = $tabIdIndiv[$indexCourant];
		
		$req = "UPDATE individu SET id_etat='3' WHERE id_individu='".$indivChoisi."'";
		if(mysql_query($req))
			$reussi = true;
		
	}
	
	return $reussi;
	
}

//Nombre réel aléatoire
function frand($intMin,$intMax,$intDecimals) {
  if($intDecimals) {
    $intPowerTen=pow(10,$intDecimals);
    return rand($intMin,$intMax*$intPowerTen)/$intPowerTen;
  }
  else
    return rand($intMin,$intMax);
}

//Enregistre les 2 nouveaux individus donnés en paramètre (format JSON)
function enregistrementNvlleGenereation($listeEnfants) {

	$reussi = true;
	if(!$liste = json_decode($listeEnfants, 1))
		$reussi = false;
	
	$indivCourant = 0;
	while($reussi and $indivCourant < count($liste['listeIndiv'])) {
	
		$req = "INSERT INTO individu values(null, 1, CURRENT_TIMESTAMP)";
		if(mysql_query($req)){

			$idIndiv = mysql_insert_id();
			
			$req = "INSERT INTO evaluation values('".idCritereDefaut."', '$idIndiv', 0.0)";
			if(mysql_query($req)){
				
				$parentCourant = 0;
				while($reussi and $parentCourant < count($liste['listeIndiv'][$indivCourant]['listeGene'])) {

					$req2 = "INSERT INTO parent values('".$liste['listeParents'][$parentCourant]['idParent']."', '$idIndiv')";
					
					if(!mysql_query($req2))
						$reussi = false;

					$parentCourant++;
				}
				
				$geneCourant = 0;
				while($reussi and $geneCourant < count($liste['listeIndiv'][$indivCourant]['listeGene'])) {

					$req2 = "INSERT INTO allele values('$idIndiv', '".$liste['listeIndiv'][$indivCourant]['listeGene'][$geneCourant]['idGene']."', '".$liste['listeIndiv'][$indivCourant]['listeGene'][$geneCourant]['alleleR']."', '".$liste['listeIndiv'][$indivCourant]['listeGene'][$geneCourant]['alleleB']."')";

					if(!mysql_query($req2))
						$reussi = false;

					$geneCourant++;

				}

			}
			else
				$reussi = false;
		}
		else
			$reussi = false;
			
		$indivCourant++;
	}
	
	return $reussi;

}

//Arrête le traitement du problème
function arreterTraitement($idProbleme) {

	$req = "UPDATE probleme SET traitement_actif='0' WHERE id_probleme='$idProbleme'";
	if(mysql_query($req))
		return true;
	else
		return false;

}

//Retourne l'état actuel de la population (nombre de création, ...)
function getEtatPop($idProbleme) {
	
	$retour = array();
	$req = "SELECT * FROM probleme WHERE id_probleme = '$idProbleme'";
	$resPb = mysql_query($req);
	$pb = mysql_fetch_array($resPb);
	if(isset($pb['min_actif']) and isset($pb['min_actif'])) {
		$retour['minActif'] = intval($pb['min_actif']);
		$retour['maxActif'] = intval($pb['max_actif']);
		$retour['maxCrea'] = intval($pb['max_creation']);
		$retour['trait'] = intval($pb['traitement_actif']);

		$req = "SELECT COUNT(DISTINCT(CASE WHEN i.id_etat = '1' THEN i.id_individu END)) as nonEval, 
			COUNT(DISTINCT(CASE WHEN i.id_etat = '2' THEN i.id_individu END)) as eval, 
			COUNT(DISTINCT(CASE WHEN i.id_etat = '3' THEN i.id_individu END)) as mort 
			FROM allele a, gene g, individu i 
			WHERE i.id_individu = a.id_individu AND a.id_gene = g.id_gene AND g.id_probleme = '$idProbleme'";
		$res = mysql_query($req);
		$nb = mysql_fetch_array($res);
		if(isset($nb[0]) and isset($nb[1]) and isset($nb[2])) {
			$retour['nonEval'] = intval($nb[0]);
			$retour['eval'] = intval($nb[1]);
			$retour['mort'] = intval($nb[2]);
		}
		
		$retour['total'] = $retour['eval'] + $retour['nonEval'] + $retour['mort'];
		$retour['actif'] = $retour['eval'] + $retour['nonEval'];
	}

	return json_encode($retour);
	
}

//Retourne le meilleur individu de la population (format JSON)
function meilleurIndiv($idProbleme) {

	$req = "SELECT id_individu FROM evaluation ORDER BY fitness DESC";
	$resIndiv = mysql_query($req);
	$indiv = mysql_fetch_array($resIndiv);
	$idIndiv = 0;
	if(isset($indiv[0]))
		$idIndiv = $indiv[0];

	return afficherIndivJSON($idIndiv);
	
}

//Modifie le nombre maximum d'individus créés (condition d'arrêt) , la taille maximale et minimale de la population, ...
function modifierTaillePop($idProbleme, $maxActif, $maxCrea, $minActif, $traitement) {

	$req = "UPDATE probleme SET max_actif='$maxActif', max_creation='$maxCrea', min_actif='$minActif', traitement_actif='$traitement' WHERE id_probleme='$idProbleme'";
	if(mysql_query($req))
		return true;
	else
		return false;
	
}

//Vide la population afin de recommencer le problème
function viderPopulation($idProbleme) {

	$req1 = "TRUNCATE individu";
	$req2 = "TRUNCATE evaluation";
	$req3 = "TRUNCATE allele";
	$req4 = "TRUNCATE parent";
	$req5 = "UPDATE probleme SET traitement_actif = '1' WHERE id_probleme='$idProbleme'";
	
	if(mysql_query($req1) and mysql_query($req2) and mysql_query($req3) and mysql_query($req4) and mysql_query($req5))
		return true;
	else
		return false;


}

?>